#pragma once

#include "../mqcommon/mq_msg.pb.h"
#include "../mqcommon/mq_helper.hpp"
#include "../mqcommon/mq_logger.hpp"

namespace mq
{
    class Router
    {
    public:
        static bool isLegalRoutingKey(const std::string &routing_key)
        {
            // 判断是否存在非法字符
            for (auto &ch : routing_key)
            {
                if (ch >= 'a' && ch <= 'z' ||
                    ch >= 'A' && ch <= 'Z' ||
                    ch >= '0' && ch <= '9' ||
                    ch == '_' || ch == '.')
                {
                    continue;
                }
                return false;
            }

            return true;
        }
        static bool isLegalBindingKey(const std::string &binding_key)
        {
            // 1.判断是否存在非法字符
            for (auto &ch : binding_key)
            {
                if (ch >= 'a' && ch <= 'z' ||
                    ch >= 'A' && ch <= 'Z' ||
                    ch >= '0' && ch <= '9' ||
                    ch == '_' || ch == '.' ||
                    ch == '*' || ch == '#')
                {
                    continue;
                }
                return false;
            }

            // 2.判断字符是否和*,#在一起
            std::vector<std::string> words;
            StrHelper::split(binding_key, ".", &words);
            for (auto &str : words)
            {
                if (str.size() > 1 &&
                    (str.find('*') != std::string::npos ||
                     str.find('#') != std::string::npos))
                {
                    return false;
                }
            }

            // 3.#的前面和后面的字串不能出现*或#
            for (int i = 1; i < words.size(); i++)
            {
                if (words[i] == "#" && words[i - 1] == "#")
                    return false;
                if (words[i] == "#" && words[i - 1] == "*")
                    return false;
                // #的后面不能出现*
                if (words[i] == "*" && words[i - 1] == "#")
                    return false;
            }

            return true;
        }
        static bool route(ExchangeType type, const std::string &routing_key, const std::string &binding_key)
        {
            if (type == ExchangeType::DIRECT)
            {
                // 直接交换
                return routing_key == binding_key;
            }
            else if (type == ExchangeType::FANOUT)
            {
                // 广播交换
                return true;
            }
            // 主题交换
            // 1. 将binding_key与routing_key进行字符串分割，得到各个的单词数组
            std::vector<std::string> rkeys;
            std::vector<std::string> bkeys;
            size_t n_rkey = StrHelper::split(routing_key, ".", &rkeys);
            size_t n_bkey = StrHelper::split(binding_key, ".", &bkeys);

            // 2. 定义标记数组，并初始化[0][0]位置为true，其他位置为false
            std::vector<std::vector<bool>> dp(n_bkey + 1, std::vector<bool>(n_rkey + 1, false));
            dp[0][0] = 1;

            // 3.如果binding_key以#起始，则将#对应行的第0列置为1
            for (int i = 1; i <= n_bkey; i++)
            {
                if (bkeys[i - 1] == "#")
                {
                    dp[i][0] = true;
                    continue;
                }
                break;
            }

            // 4. 使用routing_key中的每个单词与binding_key中的每个单词进行匹配并标记数组
            for (int i = 1; i <= n_bkey; i++)
            {
                for (int j = 1; j <= n_rkey; j++)
                {
                    // 如果当前bkey是个*，或者两个单词相同，表示单词匹配成功，则从左上方继承结果
                    if (bkeys[i - 1] == rkeys[j - 1] || bkeys[i - 1] == "*")
                    {
                        dp[i][j] = dp[i - 1][j - 1];
                    }
                    else if (bkeys[i - 1] == "#")
                    {
                        // 如果当前bkey是个#，则需要从左上，左边，上边继承结果
                        dp[i][j] = dp[i - 1][j - 1] | dp[i][j - 1] | dp[i - 1][j];
                    }
                }
            }

            return dp[n_bkey][n_rkey];
        }
    };
}
